# -*- coding: utf-8 -*-
"""
Module Description: 数据源定义,chaos多数据源支持
Date: 2018/3/23
Author:Bai Jin Ping
"""
import threading

from common import service_config
# from common.zk_config import DatabaseNameMappingConfig


class AbstractDatasource(object):
    """数据源抽象基类"""
    # 数据源特殊名称
    special_name = None

    def __enter__(self):
        datasource_context_storage.set_current_datasource(self)

    def __exit__(self, exc_type, exc_val, exc_tb):
        datasource_context_storage.clear_current_datasource()

    @classmethod
    def get_datasource_name(cls):
        """获得数据源名称"""
        raise NotImplementedError


class AreaServerDatasource(AbstractDatasource):
    """区服数据源"""

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        server_id = service_config.get_server_id()
        return DatabaseNameMappingConfig.get_server_scope_db_name(app_id=app_id, srv_id=server_id)


class CrossBaseDatasource(AbstractDatasource):
    """跨服数据源基类"""

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossRankActivityDatasource(AbstractDatasource):
    """跨服冲榜活动数据源"""
    special_name = 'cross_rank_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossSiegeActivityDatasource(AbstractDatasource):
    """跨服攻城活动数据源"""
    special_name = 'cross_siege_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossRuinsRoleDatasource(AbstractDatasource):
    """跨服遗迹争霸数据源"""
    special_name = 'cross_ruins_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CharacterCenterDatasource(AbstractDatasource):
    """角色中心数据源"""
    special_name = 'character_center'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossPrinceMarryDatasource(AbstractDatasource):
    """跨服联姻数据源"""
    special_name = 'cross_prince_marry'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossCateActivityDatasource(AbstractDatasource):
    """跨服美食活动数据源"""
    special_name = 'cross_cate_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossChessActivityDatasource(AbstractDatasource):
    """跨服组队活动数据源"""
    special_name = 'cross_chess_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossSoccerActivityDatasource(AbstractDatasource):
    """跨服足球活动数据源"""
    special_name = 'cross_soccer_activity'

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossRehearseActivityDatasource(AbstractDatasource):
    """跨服健锐训练活动数据源"""
    special_name = "cross_rehearse_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossAlliesDatasource(AbstractDatasource):
    """同盟国数据源"""
    special_name = "cross_allies"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossNaadamActivityDatasource(CrossBaseDatasource):
    """跨服那达慕活动数据源"""
    special_name = "cross_naadam_activity"


class CrossSaintActivityDatasource(CrossBaseDatasource):
    """跨服圣君登基活动数据源"""
    special_name = "cross_saint_activity"


class CrossContendActivityDatasource(CrossBaseDatasource):
    """跨服百家争鸣活动数据源"""
    special_name = "cross_contend_activity"


class CrossFestivalShopActivityDatasource(CrossBaseDatasource):
    """跨服节日商城活动数据源"""
    special_name = "cross_festival_shop_activity"


class CrossLotteryActivityDatasource(CrossBaseDatasource):
    """跨服抽奖活动数据源"""
    special_name = "cross_lottery_activity"


class CrossMonopolyActivityDatasource(CrossBaseDatasource):
    """大富翁活动数据源"""
    special_name = "cross_monopoly_activity"


class CrossQueenActivityDatasource(AbstractDatasource):
    """跨服如意赠佳人数据源"""
    special_name = "cross_queen_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossBanquetActivityDatasource(AbstractDatasource):
    """跨服满汉全席数据源"""
    special_name = "cross_banquet_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossIslandActivityDatasource(AbstractDatasource):
    """跨服蓬莱仙岛数据源"""
    special_name = "cross_island_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossSeasonActivityDatasource(AbstractDatasource):
    """跨服九州之巅数据源"""
    special_name = "cross_season_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossGroupPurchaseActivityDatasource(CrossBaseDatasource):
    """跨服团购活动数据源"""
    special_name = "cross_group_purchase_activity"


class LiveActivityDatasource(AbstractDatasource):
    """直播活动数据源"""
    special_name = "live_activity"

    @classmethod
    def get_datasource_name(cls):
        app_id = service_config.get_app_id()
        return DatabaseNameMappingConfig.get_application_scope_db_name(app_id=app_id, special_name=cls.special_name)


class CrossSiegelordActivityDatasource(CrossBaseDatasource):
    """跨服攻城掠地"""
    special_name = "cross_siegelord_activity"


class CrossClearanceActivityDatasource(CrossBaseDatasource):
    """跨服三消数据源"""
    special_name = "cross_clearance_activity"


class CrossCeladonActivityDatasource(CrossBaseDatasource):
    """青瓷御器活动数据源"""
    special_name = "cross_celadon_activity"


class CrossFightActivityDatasource(CrossBaseDatasource):
    """皇决之选"""
    special_name = "cross_fight_activity"


class CrossTowerActivityDatasource(CrossBaseDatasource):
    """楼兰古国活动数据源"""
    special_name = "cross_tower_activity"


class CrossDinnerActivityDatasource(CrossBaseDatasource):
    """跨服宴会"""
    special_name = "cross_dinner_activity"


class CrossFishActivityDatasource(CrossBaseDatasource):
    """御海垂纶"""
    special_name = "cross_fish_activity"


def set_default_datasource(datasource_class):
    """设置默认数据源类型"""
    global default_datasource_instance
    default_datasource_instance = datasource_class()


def get_default_datasource_instance():
    """获取默认数据源类型实例"""
    return default_datasource_instance


# 默认数据源类型实例
default_datasource_instance = AreaServerDatasource()


class DatasourceContextStorage(threading.local):
    """
    数据源上下文存储(线程本地变量)
    """
    initialized = False

    # 数据源上下文对象
    ctx = None
    # 同源上下文嵌套深度
    nest_depth = 0

    def __init__(self, **kw):
        if self.initialized:
            raise SystemError('__init__ called too many times')

        self.initialized = True
        self.__dict__.update(kw)

    def set_current_datasource(self, datasource):
        """设置当前数据源"""
        # 只有同数据源允许嵌套
        if self.ctx is not None:
            assert self.nest_depth != 0
            assert self.ctx.get_datasource_name() == datasource.get_datasource_name()

        self.nest_depth += 1
        self.ctx = datasource

    def clear_current_datasource(self):
        """清除当前数据源"""
        self.nest_depth -= 1

        if self.nest_depth == 0:
            self.ctx = None

    def get_db_name_for_chaos(self):
        """注册到chaos_orm sdk获取数据库名称的方法"""
        if self.ctx is None:
            # 使用默认数据源获得数据库名称
            return get_default_datasource_instance().get_datasource_name()

        return self.ctx.get_datasource_name()


datasource_context_storage = DatasourceContextStorage()


class BaseDatasourceCharacterModel(object):
    """指定数据源的模型基类"""

    # 所属数据源
    _datasource_instance = None

    @classmethod
    def set_datasource(cls, datasource):
        """设置数据源"""
        cls._datasource_instance = datasource()

    @classmethod
    def get_datasource(cls):
        """获取数据源"""
        return cls._datasource_instance if cls._datasource_instance is not None else get_default_datasource_instance()


def datasource_register(datasource):
    """
    注册数据源
    :param datasource: 数据源类
    :return:
    """
    def decorator(cls):
        cls.set_datasource(datasource)
        return cls
    return decorator

